import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
 * 位置服务管理类
 * 提供多种位置获取方式，包括IP地理位置查询、缓存管理等
 */
public class LocationService {
    
    // 免费的IP地理位置API服务
    private static final String[] IP_LOCATION_APIS = {
        "http://ip-api.com/json/",           // 免费，每分钟1000次请求
        "https://ipapi.co/json/",            // 免费，每天1000次请求
        "https://freegeoip.app/json/"        // 免费备用服务
    };
    
    private static final int CONNECTION_TIMEOUT = 8000; // 8秒连接超时
    private static final int READ_TIMEOUT = 8000;       // 8秒读取超时
    private static final long CACHE_EXPIRE_TIME = TimeUnit.HOURS.toMillis(1); // 1小时缓存过期
    
    private GeoLocationData cachedLocation;
    private UserPreferences userPreferences;
    private boolean serviceEnabled = true;
    
    public LocationService(UserPreferences userPreferences) {
        this.userPreferences = userPreferences;
    }
    
    /**
     * 异步获取当前位置
     */
    public CompletableFuture<GeoLocationData> getCurrentLocationAsync() {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return getCurrentLocation();
            } catch (Exception e) {
                throw new RuntimeException("Failed to get current location: " + e.getMessage(), e);
            }
        });
    }
    
    /**
     * 同步获取当前位置
     */
    public GeoLocationData getCurrentLocation() throws Exception {
        // 检查服务是否启用
        if (!serviceEnabled || !userPreferences.isAutoLocationEnabled()) {
            throw new Exception("Location service is disabled");
        }
        
        // 检查缓存是否有效
        if (cachedLocation != null && 
            cachedLocation.isValid() && 
            !cachedLocation.isExpired(CACHE_EXPIRE_TIME)) {
            System.out.println("Using cached location: " + cachedLocation.getDisplayString());
            return cachedLocation;
        }
        
        // 尝试从多个API获取位置
        Exception lastException = null;
        for (String apiUrl : IP_LOCATION_APIS) {
            try {
                System.out.println("Trying location API: " + apiUrl);
                GeoLocationData location = fetchLocationFromAPI(apiUrl);
                
                if (location != null && location.isValid()) {
                    location.setLocationSource("ip");
                    cachedLocation = location;
                    System.out.println("Successfully got location: " + location.getDisplayString());
                    return location;
                }
                
            } catch (Exception e) {
                lastException = e;
                System.err.println("Failed to get location from " + apiUrl + ": " + e.getMessage());
                continue;
            }
        }
        
        throw new Exception("All location APIs failed", lastException);
    }
    
    /**
     * 从指定API获取位置信息
     */
    private GeoLocationData fetchLocationFromAPI(String apiUrl) throws Exception {
        URL url = URI.create(apiUrl).toURL();
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        
        try {
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(CONNECTION_TIMEOUT);
            conn.setReadTimeout(READ_TIMEOUT);
            conn.setRequestProperty("User-Agent", "WeatherApp/1.0");
            
            int responseCode = conn.getResponseCode();
            if (responseCode != 200) {
                throw new Exception("HTTP " + responseCode + " response from " + apiUrl);
            }
            
            // 读取响应
            StringBuilder response = new StringBuilder();
            try (Scanner scanner = new Scanner(conn.getInputStream())) {
                while (scanner.hasNext()) {
                    response.append(scanner.nextLine());
                }
            }
            
            return parseLocationResponse(response.toString(), apiUrl);
            
        } finally {
            conn.disconnect();
        }
    }
    
    /**
     * 解析位置API响应
     */
    private GeoLocationData parseLocationResponse(String jsonResponse, String apiUrl) throws Exception {
        try {
            JsonObject json = JsonParser.parseString(jsonResponse).getAsJsonObject();
            GeoLocationData location = new GeoLocationData();
            
            if (apiUrl.contains("ip-api.com")) {
                return parseIpApiResponse(json);
            } else if (apiUrl.contains("ipapi.co")) {
                return parseIpapiResponse(json);
            } else if (apiUrl.contains("freegeoip.app")) {
                return parseFreeGeoIpResponse(json);
            }
            
            throw new Exception("Unknown API format");
            
        } catch (Exception e) {
            throw new Exception("Failed to parse location response: " + e.getMessage());
        }
    }
    
    /**
     * 解析ip-api.com的响应
     */
    private GeoLocationData parseIpApiResponse(JsonObject json) throws Exception {
        String status = json.has("status") ? json.get("status").getAsString() : "";
        if (!"success".equals(status)) {
            String message = json.has("message") ? json.get("message").getAsString() : "Unknown error";
            throw new Exception("IP-API error: " + message);
        }
        
        GeoLocationData location = new GeoLocationData();
        location.setLatitude(json.get("lat").getAsDouble());
        location.setLongitude(json.get("lon").getAsDouble());
        location.setCity(json.get("city").getAsString());
        location.setRegion(json.get("regionName").getAsString());
        location.setCountry(json.get("country").getAsString());
        location.setCountryCode(json.get("countryCode").getAsString());
        location.setPostalCode(json.has("zip") ? json.get("zip").getAsString() : "");
        location.setTimezone(json.has("timezone") ? json.get("timezone").getAsString() : "");
        location.setIsp(json.has("isp") ? json.get("isp").getAsString() : "");
        location.setAccuracy(5000.0); // IP定位精度通常为5km
        
        return location;
    }
    
    /**
     * 解析ipapi.co的响应
     */
    private GeoLocationData parseIpapiResponse(JsonObject json) throws Exception {
        if (json.has("error") && json.get("error").getAsBoolean()) {
            String reason = json.has("reason") ? json.get("reason").getAsString() : "Unknown error";
            throw new Exception("IPAPI error: " + reason);
        }
        
        GeoLocationData location = new GeoLocationData();
        location.setLatitude(json.get("latitude").getAsDouble());
        location.setLongitude(json.get("longitude").getAsDouble());
        location.setCity(json.get("city").getAsString());
        location.setRegion(json.get("region").getAsString());
        location.setCountry(json.get("country_name").getAsString());
        location.setCountryCode(json.get("country").getAsString());
        location.setPostalCode(json.has("postal") ? json.get("postal").getAsString() : "");
        location.setTimezone(json.has("timezone") ? json.get("timezone").getAsString() : "");
        location.setIsp(json.has("org") ? json.get("org").getAsString() : "");
        location.setAccuracy(8000.0); // IP定位精度估计
        
        return location;
    }
    
    /**
     * 解析freegeoip.app的响应
     */
    private GeoLocationData parseFreeGeoIpResponse(JsonObject json) throws Exception {
        GeoLocationData location = new GeoLocationData();
        location.setLatitude(json.get("latitude").getAsDouble());
        location.setLongitude(json.get("longitude").getAsDouble());
        location.setCity(json.get("city").getAsString());
        location.setRegion(json.get("region_name").getAsString());
        location.setCountry(json.get("country_name").getAsString());
        location.setCountryCode(json.get("country_code").getAsString());
        location.setPostalCode(json.has("zip_code") ? json.get("zip_code").getAsString() : "");
        location.setTimezone(json.has("time_zone") ? json.get("time_zone").getAsString() : "");
        location.setAccuracy(10000.0); // IP定位精度估计
        
        return location;
    }
    
    /**
     * 清除缓存的位置
     */
    public void clearCache() {
        cachedLocation = null;
        System.out.println("Location cache cleared");
    }
    
    /**
     * 获取缓存的位置
     */
    public GeoLocationData getCachedLocation() {
        if (cachedLocation != null && 
            cachedLocation.isValid() && 
            !cachedLocation.isExpired(CACHE_EXPIRE_TIME)) {
            return cachedLocation;
        }
        return null;
    }
    
    /**
     * 检查位置服务是否可用
     */
    public boolean isServiceAvailable() {
        return serviceEnabled && userPreferences.isAutoLocationEnabled();
    }
    
    /**
     * 启用/禁用位置服务
     */
    public void setServiceEnabled(boolean enabled) {
        this.serviceEnabled = enabled;
        if (!enabled) {
            clearCache();
        }
    }
    
    /**
     * 测试位置服务连接
     */
    public boolean testLocationService() {
        try {
            // 快速测试第一个API的连通性
            URL url = URI.create(IP_LOCATION_APIS[0]).toURL();
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("HEAD");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            
            int responseCode = conn.getResponseCode();
            conn.disconnect();
            
            return responseCode == 200;
            
        } catch (Exception e) {
            System.err.println("Location service test failed: " + e.getMessage());
            return false;
        }
    }
    
    /**
     * 获取位置服务状态信息
     */
    public String getServiceStatus() {
        if (!userPreferences.isAutoLocationEnabled()) {
            return "Disabled by user";
        }
        if (!serviceEnabled) {
            return "Service disabled";
        }
        if (cachedLocation != null && !cachedLocation.isExpired(CACHE_EXPIRE_TIME)) {
            return "Using cached location (" + cachedLocation.getDisplayString() + ")";
        }
        if (testLocationService()) {
            return "Available";
        } else {
            return "Network error";
        }
    }
} 